package neichuan.server.message;

import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import neichuan.AttributeKeys;
import neichuan.WorkSpace;
import neichuan.center.ExchangeCenter;
import neichuan.center.RegistCenter;
import neichuan.message.Message;
import neichuan.message.MessageHeaderFiled;
import neichuan.message.MessageType;
import neichuan.util.log.Log;

import java.net.InetSocketAddress;

public class RegisterServerHandler extends ChannelInboundHandlerAdapter {
    RegistCenter registCenter;
    /**
     * 通道类型：
     * -1：通道尚未注册
     * 0：持久通道
     * 1：临时通道
     */
    int channelType=-1;
    Channel browserChannel;
    int mainPort;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        if(registCenter==null){
            registCenter= WorkSpace.getSingleInstance().getRegistCenter();
        }

        ctx.fireChannelRegistered();
    }


    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Message m=(Message)msg;

        int type = m.getType();
        if(type== MessageType.REGIST_PORT.getType() && channelType==-1){
            //为代理客户端注册端口，并开启服务
            deal_REGIST_PORT(ctx,m);
        }
        else if(type==MessageType.REGIST_TEMP_CONNECTION.getType() && channelType==-1){
            //与代理客户端建立了临时连接，利用临时连接转发浏览器数据
            deal_REGIST_TEMP_CONNECTION(ctx,m);

        }
        else if(type==MessageType.TOMCAT_DATA.getType() && channelType==1) {
            //转发tomcat数据
            deal_TOMCAT_DATA(ctx,m);
        }

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if(Log.isDebugEnabled()){
            Log.debug("通道"+ctx.channel().localAddress()+" | "+ctx.channel().remoteAddress()+"关闭");
        }

        if(channelType==0){
            registCenter.remove(mainPort,ctx.channel());
        }
        else if(channelType==1){
            if(browserChannel!=null){
                browserChannel.close();
            }
        }
        ctx.fireChannelInactive();
    }

    public void deal_REGIST_PORT(ChannelHandlerContext ctx,Message m){
        //持久通道
        //为客户端启用该端口服务
        int port=Integer.valueOf(m.getHeader(MessageHeaderFiled.PORT.getFiled()));
        this.mainPort=port;
        //注册，启动服务器
        boolean b = registCenter.registPortAndStart(port, ctx.channel());
        //注册关闭事件，关闭的时候从集合中移除
        if(b==false){
            //注册失败或启动服务器失败，发回失败消息
            channelType=-1;
            ctx.channel().writeAndFlush(new Message(MessageType.REGIST_PORT_FAIL,null,null)).addListener(
                    new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) throws Exception {
                            //发送失败
                            if(!future.isSuccess()){
//                                registCenter.remove(port,ctx.channel());
                                ctx.close();
                            }
                        }
                    }
            );
        }
        else {
            this.channelType=0;
            //启动成功
            //发送成功消息
            ctx.channel().writeAndFlush(new Message(MessageType.REGIST_PORT_SUCCESS,null,null)).addListener(
                    new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) throws Exception {
                            //发送失败
                            if(!future.isSuccess()){
                                ctx.close();
                            }
                        }
                    }
            );
        }
    }



    public void deal_REGIST_TEMP_CONNECTION(ChannelHandlerContext ctx,Message m){
        //客户端发送过来的临时连接
        int port=Integer.valueOf(m.getHeader(MessageHeaderFiled.PORT.getFiled()));
        ExchangeCenter exchangeCenter = registCenter.getExchangeCenter(port);
        Channel mainChannel =null;
        if(exchangeCenter!=null){
            mainChannel=exchangeCenter.getMainChannel();
        }
        String cHostName=((InetSocketAddress)(ctx.channel().remoteAddress())).getHostName();
        String mainHostName=null;
        if(mainChannel!=null){
            mainHostName=((InetSocketAddress)(mainChannel.remoteAddress())).getHostName();
        }

        //验证两个通道是同一个主机发送过来的吗
        if(cHostName.equals( mainHostName)){
            //获取需要处理的浏览器通道
            browserChannel = exchangeCenter.getBrowserChannel();
            if (browserChannel!=null && browserChannel.isActive()){
                //浏览器通道需要处理
                //将临时通道给浏览器通道
                if(Log.isDebugEnabled()){
                    Log.debug("收到临时连接"+ctx.channel().remoteAddress()+"|"+ctx.channel().localAddress()+"，并唤醒浏览器通道读事件"+browserChannel.remoteAddress()+"|"+browserChannel.localAddress());
                }
                browserChannel.attr(AttributeKeys.CHANNEL.key).set(ctx.channel());
                //唤醒浏览器通道的读事件
                browserChannel.config().setOption(ChannelOption.AUTO_READ,true);
//                    browserChannel.config().setAutoRead(true);
            }
            else {
                //浏览器通道不需要处理，关闭临时通道
                ctx.close();
            }

            //注册临时通道
//                exchangeCenter.addAvailableChannel(ctx.channel());
            this.channelType=1;
        }else {
            //非法连接，直接断开临时连接
            Log.warn("有尝试连接的非法通道，该临时通道的主机地址与主通道的地址不一致，临时通道地址："+cHostName+",主通道地址："+mainHostName);
            ctx.close();
        }
    }

    public void deal_TOMCAT_DATA(ChannelHandlerContext ctx,Message m){
        //由于上面已经验证过临时连接是否为非法连接，非法连接都被抛弃了，所以此处不需要再次验证
        //处理客户端发送过来的tomcat的数据
        //临时连接发送过来的数据
        if(browserChannel.isActive()){
            //浏览器通道活跃，发送数据
            if(m.getContent_length()>0){
                ByteBuf byteBuf =browserChannel.alloc().buffer();
                byteBuf.writeBytes(m.getData());
                browserChannel.writeAndFlush(byteBuf).addListener(
                        new ChannelFutureListener() {
                            @Override
                            public void operationComplete(ChannelFuture future) throws Exception {
                                if(future.isSuccess()){
                                    if(Log.isDebugEnabled()){
                                        Log.debug(ctx.channel().remoteAddress()+"|"+ctx.channel().localAddress()+"发送数据至浏览器成功");
                                    }
                                }
                                else {
                                    if(Log.isDebugEnabled()){
                                        Log.debug(ctx.channel().remoteAddress()+"|"+ctx.channel().localAddress()+"发送数据至浏览器失败");
                                    }
                                }
                            }
                        }
                );
                byteBuf.release();
            }
        }
        else {
            //浏览器通道关闭，关闭当前通道
            ctx.close();
        }
    }


}
